/******************************************************
  mekvs.c 
******************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#else
#include <unistd.h>
#endif

#include <event2/event.h>
#include <event2/buffer.h>
#include <event2/http.h>

#include "cJson.h"
#include "sqlite3.h"

#define HTTP_PORT       4165
#define DATABASE_DIR    "./database"
#define CONDIF_DB       "./database/mekvs.db"

static char **_splite (const char *s, const char *c, size_t *n);

/******************************************************
  data 
******************************************************/

typedef struct Param {
	char *session;
	char *db;
	char *key;
    char *action;
    char *dbname;
    char *newsession;
	char *addsession;
	char *session_son;
	char *d_name;
	char *page;

	const char *_session;
	const char *_db;
	const char *_key;
	const char *_action;
	const char *_dbname;
	const char *_newsession;
	const char *_addsession;
	const char *_session_son;
	const char *_d_name;
	const char *_page;
} Param;

typedef struct User {
    int u_id;
    const char *u_session;
    int u_level;
} User;

typedef struct DataRoute {
	Param *param;
	User *user;
	struct evbuffer *buf;
} DataRoute;

/** 解析a=1&b=2... **/
static void param_parse (const char *s, Param *p) {
	size_t i = 0, n = 0;
	char **ret = NULL;

	memset(p, 0, sizeof(Param));
	ret = _splite(s, "&", &n);

	for (i = 0; i < n; i++) {
		if (strncmp(ret[i], "session=", 8) == 0) {
			p->session = ret[i];
			p->_session = ret[i] + 8;
		} else if (strncmp(ret[i], "db=", 3) == 0) {
			p->db = ret[i];
			p->_db = ret[i] + 3;
		} else if (strncmp(ret[i], "key=", 4) == 0) {
			p->key = ret[i];
			p->_key = ret[i] + 4;
		} else if (strncmp(ret[i], "action=", 7) == 0) {
			p->action = ret[i];
			p->_action = ret[i] + 7;
		} else if (strncmp(ret[i], "dbname=", 7) == 0) {
			p->dbname = ret[i];
			p->_dbname = ret[i] + 7;
		} else if (strncmp(ret[i], "newsession=", 11) == 0) {
			p->newsession = ret[i];
			p->_newsession = ret[i] + 11;
		} else if (strncmp(ret[i], "addsession=", 11) == 0) {
			p->addsession = ret[i];
			p->_addsession = ret[i] + 11;
		} else if (strncmp(ret[i], "session_son=", 12) == 0) {
			p->session_son = ret[i];
			p->_session_son = ret[i] + 12;
		} else if (strncmp(ret[i], "d_name=", 7) == 0) {
			p->d_name = ret[i];
			p->_d_name = ret[i] + 7;
		} else if (strncmp(ret[i], "page=", 5) == 0) {
			p->page = ret[i];
			p->_page = ret[i] + 5;
		} else
			free(ret[i]);
	}
	free(ret);
}

static void param_free (Param p) {
	if (p.session) free(p.session);
	if (p.db) free(p.db);
	if (p.key) free(p.key);
	if (p.action) free(p.action);
	if (p.dbname) free(p.dbname);
	if (p.newsession) free(p.newsession);
	if (p.addsession) free(p.addsession);
	if (p.session_son) free(p.session_son);
	if (p.d_name) free(p.d_name);
	if (p.page) free(p.page);

	p.session = NULL;
	p.db = NULL;
	p.key = NULL;
	p.action = NULL;
	p.dbname = NULL;
	p.newsession = NULL;
	p.addsession = NULL;
	p.session_son = NULL;
	p.d_name = NULL;
	p.page = NULL;
}

/******************************************************
  function 
******************************************************/

/** 分割字符串 **/
static char **_splite (const char *s, const char *c, size_t *n) {
    char **retData = NULL;

    const char *p = s, *left = s;
    size_t i = 0, retLen = 0;

    if (!s || !c || !n) return NULL;

    if (*s == '\0' || *c == '\0') {
        retData = (char **)calloc(1, sizeof(char *));
        if (!retData) return NULL;
        retData[0] = strdup(s);
        if (!retData[0]) { free(retData); return NULL; }
        *n = 1;
        return retData;
    }

    /** 计算个数 **/
    retLen = 1;
    while (p = strstr(p, c)) {
        p += strlen(c); retLen++;
    }
    
    retData = (char **)calloc(retLen, sizeof(char *));
    if (!retData) return NULL;

    p = s;
    while ((p = strstr(p, c)) != NULL && i < retLen) {
        if (p == left) {
            retData[i] = strdup("\0");
        } else {
            retData[i] = (char *)calloc(p - left + 1, sizeof(char));
            if (retData[i]) memcpy(retData[i], left, p - left);
        }

        i++;
        p += strlen(c);
        left = p;
    }
    retData[i++] = strdup(left);

    /** 检查空值 **/
    for (i = 0; i < retLen; i++) {
        if (retData[i] == NULL) {
            for (i = 0; i < retLen; i++)
                if (retData[i]) free(retData[i]);
            free(retData);
            return NULL;
        }
    }

    *n = retLen;
    return retData;
}

static char *_addstr2 (const char *s1, const char *s2) {
    char *s = NULL;
    size_t n = strlen(s1) + strlen(s2) + 2;

    s = (char *)calloc(1, n);
    if (!s)
        return NULL;

    sprintf(s, "%s%s", s1, s2);
    return s;
}

static char *_addstr3 (const char *s1, const char *s2, const char *s3) {
    char *s = NULL;
    size_t n = strlen(s1) + strlen(s2) + strlen(s3) + 2;

    s = (char *)calloc(1, n);
    if (!s)
        return NULL;

    sprintf(s, "%s%s%s", s1, s2, s3);
    return s;
}

static char *_addstr4 (const char *s1, const char *s2, const char *s3, const char *s4) {
    char *s = NULL;
    size_t n = strlen(s1) + strlen(s2) + strlen(s3) + strlen(s4) + 2;

    s = (char *)calloc(1, n);
    if (!s)
        return NULL;

    sprintf(s, "%s%s%s%s", s1, s2, s3, s4);
    return s;
}

/** HTTP返回 **/
static void http_result (struct evhttp_request *req, const char *msg) {
    struct evbuffer *buf = NULL;

    if (!(buf = evbuffer_new())) {
        evhttp_send_error(req, HTTP_SERVUNAVAIL, 0);
		return;
    }

    evbuffer_add_printf(buf, "%s", msg);
	evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html;charset-utf8");
    evhttp_send_reply(req, HTTP_OK, "OK", buf);
    evbuffer_free(buf);
}

/** 接口返回 **/
static void api_result (struct evhttp_request *req, int ret, const char *msg) {
    struct evbuffer *buf = NULL;

    if (!(buf = evbuffer_new())) {
        evhttp_send_error(req, HTTP_SERVUNAVAIL, 0);
		return;
    }

    evbuffer_add_printf(buf, "{\"ret\":%d, \"msg\":\"%s\"}", ret, msg);
	evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html;charset-utf8");
    evhttp_send_reply(req, HTTP_OK, "OK", buf);
    evbuffer_free(buf);
}

/** 错误返回 **/
static void error_result (struct evhttp_request *req, int ret, const char *msg) {
    struct evbuffer *buf = NULL;

    if (!(buf = evbuffer_new())) {
        evhttp_send_error(req, HTTP_SERVUNAVAIL, 0);
		return;
    }

    evbuffer_add_printf(buf, "{\"ret\":%d, \"msg\":\"%s\"}", ret, msg);
	evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html;charset-utf8");
    evhttp_send_reply(req, HTTP_BADREQUEST, " Error", buf);
    evbuffer_free(buf);
}

/** 数据返回 **/
static void data_result (struct evhttp_request *req, const void *data, int size) {
    struct evbuffer *buf = NULL;

    if (!(buf = evbuffer_new())) {
        evhttp_send_error(req, HTTP_SERVUNAVAIL, 0);
		return;
    }

    evbuffer_add(buf, data, size);
    evhttp_send_reply(req, HTTP_OK, "OK", buf);
    evbuffer_free(buf);
}

/******************************************************
  database 
******************************************************/

static int db_exist_proc (void *notused, int argc, char *argv[], char **szColName) {
	int *flag = (int *)notused;
	*flag = 1;
	return 0;
}

/**
 * 数据是否存在
 * 0 不存在
 * 1 存在
 * 2 出错
**/
static int db_exist (sqlite3 *db, const char *sql) {
    int ret = 0, flag = 0;

    ret = sqlite3_exec(db, sql, db_exist_proc, (void *)&flag, NULL);
    if (ret != SQLITE_OK) {
		return 2;
    }

	return flag;
}

/** 初始化配置数据库 **/
static void db_cfg_init () {
    int ret = 0;
    sqlite3 *db = NULL;

    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK) {
        fprintf(stderr, "db error");
        exit(0);
    }

	//基础表
    ret = sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS dbs(d_id INTEGER PRIMARY KEY AUTOINCREMENT, d_name TEXT)", NULL, 0, 0);
    if (ret != SQLITE_OK) {
        fprintf(stderr, "db error");
        exit(0);
    }

    ret = sqlite3_exec(db, 
		"CREATE TABLE IF NOT EXISTS users(u_id INTEGER PRIMARY KEY AUTOINCREMENT, u_session TEXT, u_level INTEGER)", NULL, 0, 0);
    if (ret != SQLITE_OK) {
        fprintf(stderr, "db error");
        exit(0);
    }

    ret = sqlite3_exec(db, 
		"CREATE TABLE IF NOT EXISTS admin(u_id INTEGER, d_id INTEGER, a_get INTEGER, a_put INTEGER)", NULL, 0, 0);
    if (ret != SQLITE_OK) {
        fprintf(stderr, "db error");
        exit(0);
    }

	//初始化数据
	ret = db_exist(db, "SELECT * FROM users WHERE u_id=1");
	if (ret == 2) {
        fprintf(stderr, "db error");
        exit(0);
	} else if (ret == 0) {
		ret = sqlite3_exec(db, "INSERT INTO users(u_id, u_session, u_level)values(1,'123456',1)", NULL, 0, 0);
		if (ret != SQLITE_OK) {
			fprintf(stderr, "db error");
			exit(0);
		}
	}

    sqlite3_close(db);
}

static int db_user_find_proc (void *notused, int argc, char *argv[], char **szColName) {
	User *user = (User *)notused;
    if (user) {
        user->u_id = atoi(argv[0]);
        user->u_level = atoi(argv[2]);
    }
	return 0;
}

/** 查询用户 **/
static int db_user_find (const char *session, User *user) {
    int ret = 0;
    sqlite3 *db = NULL;
    char *sql = NULL;

    sql = _addstr3("SELECT * FROM users WHERE u_session='", session, "'");
    if (!sql)
        return 0;
    
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK) {
        free(sql);
        return 0;
    }
    
    ret = sqlite3_exec(db, sql, db_user_find_proc, (void *)user, NULL);
    free(sql);
    sqlite3_close(db);
    
    if (ret != SQLITE_OK) {
		return 0;
    }

    user->u_session = session;
	return user->u_id != 0;
}

/** 更新session **/
static int db_user_newsession (int id, const char *new_session) {
    int ret = 0;
    sqlite3 *db = NULL;
    char *sql = NULL;
    char buf[125] = {0};
    User user = {0};

    //session冲突
    if (db_user_find(new_session, &user) && user.u_id != id) {
        return 0;
    }

    sprintf(buf, "%d", id);
    sql = _addstr4("UPDATE users set u_session='", new_session, "' WHERE u_id=", buf);
    if (!sql)
        return 0;
    
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK) {
        free(sql);
        return 0;
    }
    
    ret = sqlite3_exec(db, sql, NULL, NULL, NULL);
    sqlite3_close(db);
    free(sql);
    return 1;
}

static int db_dbs_select_proc1_proc (void *notused, int argc, char *argv[], char **szColName) {
	DataRoute *router = (DataRoute *)notused;

    evbuffer_add_printf(router->buf, "<tr>");
    evbuffer_add_printf(router->buf, "<td>%s</td>", argv[0]);
    evbuffer_add_printf(router->buf, "<td>%s</td>", argv[1]);
    evbuffer_add_printf(router->buf, "<td>");
    evbuffer_add_printf(router->buf, "<a href=\"/admin/session=%s&action=select&db=%s&page=0\">[select]</a>&nbsp;",
		router->user->u_session, argv[1]);
    evbuffer_add_printf(router->buf, "</td>");
    evbuffer_add_printf(router->buf, "</tr>");
	return 0;
}

/** 查询数据库 **/
static void db_dbs_select_proc1 (DataRoute *router) {
    int ret = 0;
    sqlite3 *db = NULL;
    
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK) {
        return;
    }
	
	sqlite3_exec(db, "SELECT * FROM dbs", db_dbs_select_proc1_proc, (void *)router, NULL);
    sqlite3_close(db);
}

static int db_dbs_select_proc2_proc (void *notused, int argc, char *argv[], char **szColName) {
	DataRoute *router = (DataRoute *)notused;

    evbuffer_add_printf(router->buf, "<tr>");
    evbuffer_add_printf(router->buf, "<td>%s</td>", argv[0]);
    evbuffer_add_printf(router->buf, "<td>%s</td>", argv[1]);
    evbuffer_add_printf(router->buf, "<td>");
    evbuffer_add_printf(router->buf, "<a href=\"/admin/session=%s&action=select&db=%s&page=0\">[select]</a>&nbsp;",
		router->user->u_session, argv[1]);
    evbuffer_add_printf(router->buf, "</td>");
    evbuffer_add_printf(router->buf, "</tr>");
	return 0;
}

/** 查询数据库 **/
static void db_dbs_select_proc2 (DataRoute *router) {
    int ret = 0;
    sqlite3 *db = NULL;
	char sql[1024] = {0};
    
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK) {
        return;
    }

	sprintf(sql, "SELECT * FROM dbs WHERE d_id IN (SELECT d_id FROM admin WHERE u_id=%d)", router->user->u_id);
	sqlite3_exec(db, sql, db_dbs_select_proc2_proc, (void *)router, NULL);
    sqlite3_close(db);
}

static int db_dbs_get_dname_proc (void *notused, int argc, char *argv[], char **szColName) {
	char **buf = (char **)notused;
	*buf = strdup(argv[1]);
	return 0;
}

/** 获得数据库名称 **/
static char *db_dbs_get_dname (const char *d_id) {
    int ret = 0;
    sqlite3 *db = NULL;
	char sql[1024] = {0}, *buf = NULL;
    
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK) {
        return NULL;
    }
	
	sprintf(sql, "SELECT * FROM dbs WHERE d_id=%s", d_id);
	sqlite3_exec(db, sql, db_dbs_get_dname_proc, (char **)&buf, NULL);
    sqlite3_close(db);
	return buf;
}

static int db_dbs_select_admin_proc (void *notused, int argc, char *argv[], char **szColName) {
	struct evbuffer *buf = (struct evbuffer *)notused;
	char *d_name = NULL;

	d_name = db_dbs_get_dname(argv[1]);
    evbuffer_add_printf(buf, "[%s][get=>%s][put=>%s]<br/>", d_name, argv[2], argv[3]);
	if (d_name) free(d_name);
	return 0;
}

/** 查询用户的权限 **/
static void db_dbs_select_admin (struct evbuffer *buf, int argc, char *argv[]) {
    int ret = 0;
    sqlite3 *db = NULL;
	char *sql = NULL;

    sql = _addstr2("SELECT * FROM admin WHERE u_id=", argv[0]);
    if (!sql)
        return;
    
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK) {
		free(sql);
        return;
    }
    
	sqlite3_exec(db, sql, db_dbs_select_admin_proc, (void *)buf, NULL);
    sqlite3_close(db);
	free(sql);
}

static int db_users_select_proc1_proc (void *notused, int argc, char *argv[], char **szColName) {
	DataRoute *router = (DataRoute *)notused;

    evbuffer_add_printf(router->buf, "<tr>");
    evbuffer_add_printf(router->buf, "<td>%s</td>", argv[0]);
    evbuffer_add_printf(router->buf, "<td>%s</td>", argv[1]);
    evbuffer_add_printf(router->buf, "<td>%s</td>", argv[2]);

    evbuffer_add_printf(router->buf, "<td>");
	db_dbs_select_admin(router->buf, argc, argv);
	evbuffer_add_printf(router->buf, "</td>");

    evbuffer_add_printf(router->buf, "<td>");
	if (atoi(argv[2]) != 1) {
		evbuffer_add_printf(router->buf, "<a href=\"javascript:open_get_admin('%s');\">[open get admin]</a>&nbsp;", argv[1]);
		evbuffer_add_printf(router->buf, "<a href=\"javascript:close_get_admin('%s');\">[close get admin]</a><br/>", argv[1]);
		evbuffer_add_printf(router->buf, "<a href=\"javascript:open_put_admin('%s');\">[open put admin]</a>&nbsp;", argv[1]);
		evbuffer_add_printf(router->buf, "<a href=\"javascript:close_put_admin('%s');\">[close put admin]</a><br/>", argv[1]);
		evbuffer_add_printf(router->buf, "<a href=\"/admin/session=%s&action=deleteuser&session_son=%s\" onclick=\"if(!confirm('area you sure?')){return false;}\">[delete]</a>",
			router->user->u_session, argv[1]);
	} else {
		evbuffer_add_printf(router->buf, "/");
	}
	evbuffer_add_printf(router->buf, "</td>");
    evbuffer_add_printf(router->buf, "</tr>");
	return 0;
}

/** 查询用户 **/
static void db_users_select_proc1 (DataRoute *router) {
    sqlite3 *db = NULL;
    
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK) {
        return;
    }
    
	sqlite3_exec(db, "SELECT * FROM users", db_users_select_proc1_proc, (void *)router, NULL);
    sqlite3_close(db);
}

static int db_db_find_proc (void *notused, int argc, char *argv[], char **szColName) {
    int *d_id = (int *)notused;
    *d_id = atoi(argv[0]);
    return 0;
}

/** 查询数据库ID **/
static int db_db_find (const char *d_name) {
    int ret = 0;
    sqlite3 *db = NULL;
    char *sql = NULL;
    int d_id = 0;

    sql = _addstr3("SELECT * FROM dbs WHERE d_name='", d_name, "'");
    if (!sql)
        return 0;
    
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK) {
        free(sql);
        return 0;
    }
    
    sqlite3_exec(db, sql, db_db_find_proc, (void *)&d_id, NULL);
    sqlite3_close(db);
    free(sql);
    return d_id;
}

/** 新建数据库对应的db文件 **/
static void db_dbs_add_db (int d_id) {
    int ret = 0;
    sqlite3 *db = NULL;
    char buf[125] = {0};

    sprintf(buf, "%s/db_%d.db", DATABASE_DIR, d_id);
    if (sqlite3_open(buf, &db) != SQLITE_OK) {
        return;
    }
    
    sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS data(d_key TEXT PRIMARY KEY, d_val BLOB)", NULL, 0, 0);
    sqlite3_close(db);
}

/** 添加数据库 **/
static void db_dbs_add (const char *dbname) {
    int d_id = 0, ret = 0;
    sqlite3 *db = NULL;
    char *sql = NULL;

    //查询此数据库是否存在
    d_id = db_db_find(dbname);
    if (d_id != 0) {
        return;
    }

    //添加一个数据库
    sql = _addstr3("INSERT INTO dbs(d_name)values('", dbname, "')");
    if (!sql) {
        return;
    }
    
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK) {
        free(sql);
        return;
    }

    ret = sqlite3_exec(db, sql, NULL, NULL, NULL);
    sqlite3_close(db);
    free(sql);

    if (ret != SQLITE_OK)
        return;

    //新建对应数据库文件
    d_id = db_db_find(dbname);
    if (d_id == 0) {
        return;
    }

    db_dbs_add_db(d_id);
}

/** 添加一个用户 **/
static void db_users_add (const char *session) {
    int ret = 0;
    sqlite3 *db = NULL;
    char *sql = NULL;
	User user = {0};

	if (db_user_find(session, &user)) {
		return;
	}

    //添加一个用户
    sql = _addstr3("INSERT INTO users(u_session,u_level)values('", session, "',0)");
    if (!sql) {
        return;
    }
    
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK) {
        free(sql);
        return;
    }

	ret = sqlite3_exec(db, sql, NULL, NULL, NULL);
    sqlite3_close(db);
    free(sql);
}

/** 删除一个用户 **/
static void db_users_del (const char *session) {
    int ret = 0;
    sqlite3 *db = NULL;
    char *sql = NULL;
	User user = {0};
	char buf[1024] = {0};

	char *err_msg = NULL;

	if (!db_user_find(session, &user)) {
		return;
	}

	//删除用户
    sql = _addstr3("DELETE FROM users WHERE u_session='", session, "' AND u_id != 1");
    if (!sql) {
        return;
    }
    
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK) {
        free(sql);
        return;
    }
	
	sqlite3_exec(db, sql, NULL, NULL, &err_msg);
    free(sql);

	//删除用户权限
	sprintf(buf, "DELETE FROM admin WHERE u_id=%d", user.u_id);
	sqlite3_exec(db, buf, NULL, NULL, NULL);

    sqlite3_close(db);
}

/** 此权限是否存在 **/
static int admin_is_exist (int u_id, int d_id) {
	char sql[1024] = {0};
    sqlite3 *db = NULL;
	int ret = 0;

	memset(sql, 0, sizeof(sql));
	sprintf(sql, "SELECT * from admin where u_id=%d and d_id=%d", u_id, d_id);
	
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK)
        return 0;

	ret = db_exist(db, sql);
	sqlite3_close(db);
	return ret;
}

/** 此权限是否存在 **/
static int admin_is_exist_get (int u_id, int d_id) {
	char sql[1024] = {0};
    sqlite3 *db = NULL;
	int ret = 0;

	memset(sql, 0, sizeof(sql));
	sprintf(sql, "SELECT * from admin where u_id=%d and d_id=%d and a_get=1", u_id, d_id);
	
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK)
        return 0;

	ret = db_exist(db, sql);
	sqlite3_close(db);
	return ret;
}

/** 此权限是否存在 **/
static int admin_is_exist_put (int u_id, int d_id) {
	char sql[1024] = {0};
    sqlite3 *db = NULL;
	int ret = 0;

	memset(sql, 0, sizeof(sql));
	sprintf(sql, "SELECT * from admin where u_id=%d and d_id=%d and a_put=1", u_id, d_id);
	
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK)
        return 0;

	ret = db_exist(db, sql);
	sqlite3_close(db);
	return ret;
}

/** 打开get权限 **/
static void open_get_admin (const char *session, const char *d_name) {
	int d_id = 0;
	User user = {0};
	
    sqlite3 *db = NULL;
	char sql[1024] = {0};

	d_id = db_db_find(d_name);
	if (d_id <= 0)
		return;

	if (!db_user_find(session, &user))
		return;
	
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK)
        return;
	
    //添加权限
	if (!admin_is_exist(user.u_id, d_id)) {
		memset(sql, 0, sizeof(sql));
		sprintf(sql, "INSERT INTO admin(u_id,d_id,a_get,a_put)VALUES(%d,%d,0,0)", user.u_id, d_id);
		sqlite3_exec(db, sql, NULL, NULL, NULL);
	}

	//打开权限
	memset(sql, 0, sizeof(sql));
	sprintf(sql, "UPDATE admin set a_get=1 WHERE u_id=%d and d_id=%d", user.u_id, d_id);
	sqlite3_exec(db, sql, NULL, NULL, NULL);

    sqlite3_close(db);
}

/** 关闭get权限 **/
static void close_get_admin (const char *session, const char *d_name) {
	int d_id = 0;
	User user = {0};
	
    sqlite3 *db = NULL;
	char sql[1024] = {0};

	d_id = db_db_find(d_name);
	if (d_id <= 0)
		return;

	if (!db_user_find(session, &user))
		return;
	
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK)
        return;
	
    //添加权限
	if (!admin_is_exist(user.u_id, d_id)) {
		memset(sql, 0, sizeof(sql));
		sprintf(sql, "INSERT INTO admin(u_id,d_id,a_get,a_put)VALUES(%d,%d,0,0)", user.u_id, d_id);
		sqlite3_exec(db, sql, NULL, NULL, NULL);
	}

	//关闭权限
	memset(sql, 0, sizeof(sql));
	sprintf(sql, "UPDATE admin set a_get=0 WHERE u_id=%d and d_id=%d", user.u_id, d_id);
	sqlite3_exec(db, sql, NULL, NULL, NULL);

    sqlite3_close(db);
}

/** 打开put权限 **/
static void open_put_admin (const char *session, const char *d_name) {
	int d_id = 0;
	User user = {0};
	
    sqlite3 *db = NULL;
	char sql[1024] = {0};

	d_id = db_db_find(d_name);
	if (d_id <= 0)
		return;

	if (!db_user_find(session, &user))
		return;
	
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK)
        return;
	
    //添加权限
	if (!admin_is_exist(user.u_id, d_id)) {
		memset(sql, 0, sizeof(sql));
		sprintf(sql, "INSERT INTO admin(u_id,d_id,a_get,a_put)VALUES(%d,%d,0,0)", user.u_id, d_id);
		sqlite3_exec(db, sql, NULL, NULL, NULL);
	}

	//打开权限
	memset(sql, 0, sizeof(sql));
	sprintf(sql, "UPDATE admin set a_put=1 WHERE u_id=%d and d_id=%d", user.u_id, d_id);
	sqlite3_exec(db, sql, NULL, NULL, NULL);

    sqlite3_close(db);
}

/** 关闭put权限 **/
static void close_put_admin (const char *session, const char *d_name) {
	int d_id = 0;
	User user = {0};
	
    sqlite3 *db = NULL;
	char sql[1024] = {0};

	d_id = db_db_find(d_name);
	if (d_id <= 0)
		return;

	if (!db_user_find(session, &user))
		return;
	
    if (sqlite3_open(CONDIF_DB, &db) != SQLITE_OK)
        return;
	
    //添加权限
	if (!admin_is_exist(user.u_id, d_id)) {
		memset(sql, 0, sizeof(sql));
		sprintf(sql, "INSERT INTO admin(u_id,d_id,a_get,a_put)VALUES(%d,%d,0,0)", user.u_id, d_id);
		sqlite3_exec(db, sql, NULL, NULL, NULL);
	}

	//关闭权限
	memset(sql, 0, sizeof(sql));
	sprintf(sql, "UPDATE admin set a_put=0 WHERE u_id=%d and d_id=%d", user.u_id, d_id);
	sqlite3_exec(db, sql, NULL, NULL, NULL);

    sqlite3_close(db);
}

/** 添加预留数据 **/
static int db_fix_data (sqlite3 *db, const char *key) {
	sqlite3_stmt *stmt = NULL;
	int ret = 0;

	ret = sqlite3_prepare_v2(db, "INSERT INTO data(d_key,d_val)VALUES(?,null)", -1, &stmt, NULL);
	if (ret != SQLITE_OK) {
		return 0;
	}

	ret = sqlite3_bind_text(stmt, 1, key, -1, NULL);
	if (ret != SQLITE_OK) {
		sqlite3_finalize(stmt);
		return 0;
	}

	ret = sqlite3_step(stmt);
	sqlite3_finalize(stmt);
	return 1;
}

/** get **/
static void db_get (struct evhttp_request *req, int d_id, const char *key) {
    char buf[125] = {0};
	int ret = 0;
    sqlite3 *db = NULL;
	sqlite3_stmt *stmt = NULL;

	const void * data = NULL;
	int size = 0;

    sprintf(buf, "%s/db_%d.db", DATABASE_DIR, d_id);
    if (sqlite3_open(buf, &db) != SQLITE_OK) {
		error_result(req, 901, "db error");
        return;
    }

	ret = sqlite3_prepare_v2(db, "SELECT * FROM data WHERE d_key=?", -1, &stmt, NULL);
	if (ret != SQLITE_OK) {
		sqlite3_close(db);
		error_result(req, 901, "db error");
        return;
	}

	ret = sqlite3_bind_text(stmt, 1, key, -1, NULL);
	if (ret != SQLITE_OK) {
		sqlite3_finalize(stmt);
		sqlite3_close(db);
		error_result(req, 901, "db error");
		return;
	}

	ret = sqlite3_step(stmt);
	if (ret != SQLITE_ROW) {
		error_result(req, 404, "key not exist");
	} else {
		data = sqlite3_column_blob(stmt, 1);
		size = sqlite3_column_bytes(stmt, 1);
		data_result(req, data, size);
	}
	sqlite3_finalize(stmt);
	sqlite3_close(db);
}

int wait_proc (void *ptr, int count) {
	return 1;
}

/** put **/
static int db_put (int d_id, const char *key, char *data, size_t size) {
    char buf[125] = {0};
	int ret = 0;
    sqlite3 *db = NULL;
	sqlite3_stmt *stmt = NULL;

    sprintf(buf, "%s/db_%d.db", DATABASE_DIR, d_id);
    if (sqlite3_open(buf, &db) != SQLITE_OK) {
        return 0;
    }

	sqlite3_exec(db, "PRAGMA synchronous = OFF;", 0, 0, 0);
	sqlite3_busy_handler(db, wait_proc, (void *)db);

	db_fix_data(db, key);

	ret = sqlite3_prepare_v2(db, "UPDATE data SET d_val=? WHERE d_key=?", -1, &stmt, NULL);
	if (ret != SQLITE_OK) {
		sqlite3_close(db);
		return 0;
	}

	ret = sqlite3_bind_blob(stmt, 1, data, size, NULL);
	if (ret != SQLITE_OK) {
		sqlite3_finalize(stmt);
		sqlite3_close(db);
		return 0;
	}

	ret = sqlite3_bind_text(stmt, 2, key, -1, NULL);
	if (ret != SQLITE_OK) {
		sqlite3_finalize(stmt);
		sqlite3_close(db);
		return 0;
	}
	
	sqlite3_step(stmt);
	sqlite3_finalize(stmt);
    sqlite3_close(db);
	return 1;
}

static int data_select_proc (void *notused, int argc, char *argv[], char **szColName) {
	DataRoute *router = (DataRoute *)notused;
	evbuffer_add_printf(router->buf, "<tr>");
	evbuffer_add_printf(router->buf, "<td>%s</td>", argv[0]);
	evbuffer_add_printf(router->buf, "<td>%s</td>", argv[1]);
	evbuffer_add_printf(router->buf, "</tr>");
	return 0;
}

/** select **/
static void data_select (DataRoute *router, int d_id) {
	sqlite3 *db = NULL;
    char buf[125] = {0};
	int page = 0;
    char sql[1024] = {0};

	if (router->param->_page) {
		page = atoi(router->param->_page);
		if (page < 0) page = 0;
	}

    sprintf(buf, "%s/db_%d.db", DATABASE_DIR, d_id);
	if (sqlite3_open(buf, &db) != SQLITE_OK) {
        return;
    }
	
	sprintf(sql, "SELECT * FROM data LIMIT %d,20", page * 20);
	evbuffer_add_printf(router->buf, "<table border=\"1\">");
	sqlite3_exec(db, sql, data_select_proc, (void *)router, NULL);
	evbuffer_add_printf(router->buf, "</table><br/>");
    sqlite3_close(db);
	
	evbuffer_add_printf(router->buf, "<a href=\"/admin/session=%s&action=select&db=%s&page=0\">[第一页]</a>", 
		router->user->u_session, router->param->_db);
	if (page > 0) {
		evbuffer_add_printf(router->buf, "<a href=\"/admin/session=%s&action=select&db=%s&page=%d\">[上一页]</a>", 
			router->user->u_session, router->param->_db, page - 1);
	}
	evbuffer_add_printf(router->buf, "<a href=\"/admin/session=%s&action=select&db=%s&page=%d\">[下一页]</a>", 
		router->user->u_session, router->param->_db, page + 1);
}

/******************************************************
  service 
******************************************************/

static void admin (struct evhttp_request *req, Param *param) {
    User user = {0};
    struct evbuffer *buf = NULL;
	DataRoute router = {0};

	if (!param->_session || *param->_session == 0 || !db_user_find(param->_session, &user)) {
		http_result(req, 
		    "<script>"
		    "var str = prompt(\"session\", \"\");"
            "var login_i = 0;"
		    "while (str == null || str.length <= 0) {"
		    "    str = prompt(\"session\", \"\"); "
            "    login_i++;"
            "    if (login_i >= 2) break;"
		    "}"
            "if (str) {"
		    "    window.location.href=\"/admin/session=\" + str; "
            "}"
		    "</script>"
	    );
        return;
	}

    if (!(buf = evbuffer_new())) {
        evhttp_send_error(req, HTTP_SERVUNAVAIL, 0);
		return;
    }

    //admin首页
    if (!param->_action || *param->_action == 0) {
        evbuffer_add_printf(buf, "%s", "<!DOCTYPE html>");
        evbuffer_add_printf(buf, "%s", "<html lang=\"en\">");
        evbuffer_add_printf(buf, "%s", "<head>");
        evbuffer_add_printf(buf, "%s", "<meta charset=\"UTF-8\">");
        evbuffer_add_printf(buf, "%s", "<title>admin</title>");
        evbuffer_add_printf(buf, "%s", "</head>");
        evbuffer_add_printf(buf, "%s", "<body>");

        evbuffer_add_printf(buf, "<h3>Hello session: %s, level: %s</h3>", 
            param->_session, user.u_level == 1 ? "admin" : "normal");

        //管理员模式,可管理用户/数据库
        if (user.u_level == 1) {
			evbuffer_add_printf(buf, 
				"<script>"
				"function new_session () {"
				"    var str = prompt(\"new session\", \"\");"
				"    if (str) {"
				"        window.location.href=\"/admin/session=%s&action=newsession&newsession=\" + str; "
				"    }"
				"}"
				"</script>", param->_session);
			evbuffer_add_printf(buf, "<a href=\"javascript:new_session();\">[new session]</a><br/><br/>");

            evbuffer_add_printf(buf, 
		        "<script>"
                "function adddb () {"
		        "    var str = prompt(\"dbname\", \"\");"
		        "    if (str) {"
		        "        window.location.href=\"/admin/session=%s&action=adddb&dbname=\" + str; "
		        "    }"
                "}"
		        "</script>", param->_session);
            evbuffer_add_printf(buf, "<a href=\"javascript:adddb();\">[adddb]</a>");

			evbuffer_add_printf(buf, 
		        "<script>"
                "function open_get_admin (session_son) {"
		        "    var d_name = prompt(\"d_name\", \"\");"
		        "    if (d_name) {"
		        "        window.location.href=\"/admin/session=%s&action=open_get_admin&session_son=\" + session_son + \"&d_name=\" + d_name; "
		        "    }"
                "}"
		        "</script>", param->_session);

			evbuffer_add_printf(buf, 
		        "<script>"
                "function close_get_admin (session_son) {"
		        "    var d_name = prompt(\"d_name\", \"\");"
		        "    if (d_name) {"
		        "        window.location.href=\"/admin/session=%s&action=close_get_admin&session_son=\" + session_son + \"&d_name=\" + d_name; "
		        "    }"
                "}"
		        "</script>", param->_session);

			evbuffer_add_printf(buf, 
		        "<script>"
                "function open_put_admin (session_son) {"
		        "    var d_name = prompt(\"d_name\", \"\");"
		        "    if (d_name) {"
		        "        window.location.href=\"/admin/session=%s&action=open_put_admin&session_son=\" + session_son + \"&d_name=\" + d_name; "
		        "    }"
                "}"
		        "</script>", param->_session);

			evbuffer_add_printf(buf, 
		        "<script>"
                "function close_put_admin (session_son) {"
		        "    var d_name = prompt(\"d_name\", \"\");"
		        "    if (d_name) {"
		        "        window.location.href=\"/admin/session=%s&action=close_put_admin&session_son=\" + session_son + \"&d_name=\" + d_name; "
		        "    }"
                "}"
		        "</script>", param->_session);

            evbuffer_add_printf(buf, "<table border=\"1\">");
            evbuffer_add_printf(buf, "<tr>");
            evbuffer_add_printf(buf, "<th>d_id</th>");
            evbuffer_add_printf(buf, "<th>d_name</th>");
            evbuffer_add_printf(buf, "<th>menu</th>");
            evbuffer_add_printf(buf, "</tr>");
			router.param = param;
			router.buf = buf;
			router.user = &user;
            db_dbs_select_proc1(&router);
            evbuffer_add_printf(buf, "</table><br/><br/>");

            
            evbuffer_add_printf(buf, 
		        "<script>"
                "function adduser () {"
		        "    var str = prompt(\"session\", \"\");"
		        "    if (str) {"
		        "        window.location.href=\"/admin/session=%s&action=adduser&addsession=\" + str; "
		        "    }"
                "}"
		        "</script>", param->_session);
            evbuffer_add_printf(buf, "<a href=\"javascript:adduser();\">[adduser]</a>");

            evbuffer_add_printf(buf, "<table border=\"1\">");
            evbuffer_add_printf(buf, "<tr>");
            evbuffer_add_printf(buf, "<th>u_id</th>");
            evbuffer_add_printf(buf, "<th>u_session</th>");
            evbuffer_add_printf(buf, "<th>u_level</th>");
            evbuffer_add_printf(buf, "<th>admin</th>");
            evbuffer_add_printf(buf, "<th>menu</th>");
            evbuffer_add_printf(buf, "</tr>");
			router.param = param;
			router.buf = buf;
			router.user = &user;
            db_users_select_proc1(&router);
            evbuffer_add_printf(buf, "</table><br/><br/>");
        }

        //非管理员模式
		else {
            evbuffer_add_printf(buf, "<table border=\"1\">");
            evbuffer_add_printf(buf, "<tr>");
            evbuffer_add_printf(buf, "<th>d_id</th>");
            evbuffer_add_printf(buf, "<th>d_name</th>");
            evbuffer_add_printf(buf, "<th>menu</th>");
            evbuffer_add_printf(buf, "</tr>");
			router.param = param;
			router.buf = buf;
			router.user = &user;
            db_dbs_select_proc2(&router);
            evbuffer_add_printf(buf, "</table><br/><br/>");
		}

        evbuffer_add_printf(buf, "%s", "</body>");
        evbuffer_add_printf(buf, "%s", "</html>");
    }

    //修改session
    else if (strcmp(param->_action, "newsession") == 0) {
        if (param->_newsession && *param->_newsession != 0 && db_user_newsession(user.u_id, param->_newsession)) {
            evbuffer_add_printf(buf, "<script>window.location.href=\"/admin/session=%s\";</script>", param->_newsession);
        } else {
            evbuffer_add_printf(buf, "<script>window.location.href=\"/admin/session=%s\";</script>", param->_session);
        }
    }

    //添加数据库
    else if (strcmp(param->_action, "adddb") == 0) {
        if (user.u_level == 1 && param->_dbname && *param->_dbname != 0)
            db_dbs_add(param->_dbname);

        evbuffer_add_printf(buf, "<script>window.location.href=\"/admin/session=%s\";</script>", param->_session);
    }

	//添加用户
    else if (strcmp(param->_action, "adduser") == 0) {
        if (user.u_level == 1 && param->_addsession && *param->_addsession != 0)
            db_users_add(param->_addsession);

        evbuffer_add_printf(buf, "<script>window.location.href=\"/admin/session=%s\";</script>", param->_session);
	}

	//打开get权限
    else if (strcmp(param->_action, "open_get_admin") == 0) {
        if (user.u_level == 1 && param->_session_son && *param->_session_son != 0)
			open_get_admin(param->_session_son, param->_d_name);

        evbuffer_add_printf(buf, "<script>window.location.href=\"/admin/session=%s\";</script>", param->_session);
	}

	//关闭get权限
    else if (strcmp(param->_action, "close_get_admin") == 0) {
        if (user.u_level == 1 && param->_session_son && *param->_session_son != 0)
			close_get_admin(param->_session_son, param->_d_name);

        evbuffer_add_printf(buf, "<script>window.location.href=\"/admin/session=%s\";</script>", param->_session);
	}

	//打开put权限
    else if (strcmp(param->_action, "open_put_admin") == 0) {
        if (user.u_level == 1 && param->_session_son && *param->_session_son != 0)
			open_put_admin(param->_session_son, param->_d_name);

        evbuffer_add_printf(buf, "<script>window.location.href=\"/admin/session=%s\";</script>", param->_session);
	}

	//关闭put权限
    else if (strcmp(param->_action, "close_put_admin") == 0) {
        if (user.u_level == 1 && param->_session_son && *param->_session_son != 0)
			close_put_admin(param->_session_son, param->_d_name);

        evbuffer_add_printf(buf, "<script>window.location.href=\"/admin/session=%s\";</script>", param->_session);
	}

	//删除用户
    else if (strcmp(param->_action, "deleteuser") == 0) {
        if (user.u_level == 1 && param->_session_son && *param->_session_son != 0)
			db_users_del(param->_session_son);

        evbuffer_add_printf(buf, "<script>window.location.href=\"/admin/session=%s\";</script>", param->_session);
	}

	//数据查询
    else if (strcmp(param->_action, "select") == 0) {
		int d_id = db_db_find(param->_db);

		evbuffer_add_printf(buf, "<a href=\"/admin/session=%s\">[home]</a><br/>", user.u_session);

		if (d_id > 0) {
			if (user.u_id != 1 && !admin_is_exist_get(user.u_id, d_id)) {
				evbuffer_add_printf(buf, "'%s' permission denied", param->_db);
			} else {
				router.param = param;
				router.buf = buf;
				router.user = &user;
				data_select(&router, d_id);
			}
		} else {
			evbuffer_add_printf(buf, "'%s' not exist", param->_db);
		}
	}

	evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html;charset-utf8");
    evhttp_send_reply(req, HTTP_OK, "OK", buf);
    evbuffer_free(buf);
}

static void get (struct evhttp_request *req, Param *param) {
    User user = {0};
	int d_id = 0;

	if (!param->_session || *param->_session == 0 || !db_user_find(param->_session, &user)) {
		error_result(req, 1, "session error");
		return;
	}

	if (!param->_key || *param->_key == 0) {
		error_result(req, 1, "key error");
		return;
	}

	if (!param->_db || *param->_db == 0 || (d_id = db_db_find(param->_db)) <= 0) {
		error_result(req, 2, "db error");
		return;
	}

	if (!admin_is_exist_get(user.u_id, d_id)) {
		error_result(req, 3, "permission denied");
		return;
	}

	db_get(req, d_id, param->_key);
}

static void put (struct evhttp_request *req, Param *param) {
	struct evbuffer *buf;
    User user = {0};
	int d_id = 0;
	
	size_t post_size = 0;
	char *data = NULL;
	int ret = 0;

	if (!param->_session || *param->_session == 0 || !db_user_find(param->_session, &user)) {
		error_result(req, 1, "session error");
		return;
	}

	if (!param->_key || *param->_key == 0) {
		error_result(req, 1, "key error");
		return;
	}

	if (!param->_db || *param->_db == 0 || (d_id = db_db_find(param->_db)) <= 0) {
		error_result(req, 2, "db error");
		return;
	}

	if (!admin_is_exist_put(user.u_id, d_id)) {
		error_result(req, 3, "permission denied");
		return;
	}

	buf = evhttp_request_get_input_buffer(req);
	post_size = evbuffer_get_length(buf);

	data = (char *)calloc(1, post_size + 1);
	if (!data) {
		error_result(req, 900, "oom");
		return;
	}
	evbuffer_remove(buf, data, post_size);

	ret = db_put(d_id, param->_key, data, post_size);
	if (ret)
		api_result(req, 0, "ok");
	else
		error_result(req, 901, "db error");
	free(data);
}

/******************************************************
  router 
******************************************************/

static void generic_handler (struct evhttp_request *req, void *arg) {
    const char *get_url = NULL;
	char *de_get_url = NULL;
	Param param = {0};
	
	get_url = evhttp_request_get_uri(req);
	de_get_url = evhttp_uridecode(get_url, 0, NULL);
	if (!de_get_url) {
		evhttp_send_error(req, HTTP_SERVUNAVAIL, 0);
		return;
	}

    if (evhttp_request_get_command(req) == EVHTTP_REQ_GET) {
        if (strncmp(de_get_url, "/get/", strlen("/get/")) == 0) {
			param_parse(de_get_url + strlen("/get/"), &param);
            get(req, &param);
        }
		
		else if (strncmp(get_url, "/admin/", strlen("/admin/")) == 0) {
			param_parse(de_get_url + strlen("/admin/"), &param);
            admin(req, &param);
        }
		
		else if (strcmp(get_url, "/") == 0) {
            http_result(req, "<script>window.location.href=\"/admin/\";</script>");
        }
		
		else {
            evhttp_send_error(req, HTTP_BADREQUEST, 0);
        }
    }
    
    else if (evhttp_request_get_command(req) == EVHTTP_REQ_POST) {
        if (strncmp(get_url, "/put/", strlen("/put/")) != 0) {
            evhttp_send_error(req, HTTP_BADREQUEST, 0);
            return;
        }
		
		param_parse(de_get_url + strlen("/put/"), &param);
		put(req, &param);
    }
    
    else {
        evhttp_send_error(req, HTTP_BADREQUEST, 0);
    }
	
	free(de_get_url);
	param_free(param);
}

int main (int argc, char *argv[]) {
    struct event_base *base = NULL;
    struct evhttp     *http_server = NULL;

#ifdef _WIN32
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2,2) , &wsaData);
#endif

    db_cfg_init();

    if (!(base = event_base_new()) || !(http_server = evhttp_new(base)))
        return 0;

    if (evhttp_bind_socket(http_server, "0.0.0.0", HTTP_PORT)) {
        fprintf(stderr, "bind failed\n");
        return 0;
    }

    evhttp_set_gencb(http_server, generic_handler, NULL);
    event_base_dispatch(base);
    evhttp_free(http_server);

#ifdef _WIN32
    WSACleanup();
#endif
    return 1;
}

